package own.stu.jobgib.playown;

import com.alibaba.fastjson.JSON;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileSystemUtils;
import org.springframework.web.client.RestTemplate;
import own.stu.jobgib.playown.alg.leetcode.editor.cn.TreeNode;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@Slf4j
public class TestON {
    private static final Logger logger = LoggerFactory.getLogger(TestON.class);

    public static void main(String[] args) throws InterruptedException, IOException {
//        String path = "/Users/qim/Documents";
        String path = "/Users/qim/Downloads/aldi/aldi-归档-0630";

        FileRemoveTargetDir fileRemoveTargetDir = new FileRemoveTargetDir(path);
        fileRemoveTargetDir.del();

        int x = 23 >> 1;

        // renameFile();
        /*System.out.println(dup("xxx.xx"));
        System.out.println(dup("xxx.xxxxx.xx"));*/

//        or();
//        interruptedThread();

//        testCatch();

//        TreeNode node = new TreeNode(1);
//        TestON t = new TestON();
//        System.out.println(t.pathSum(node, 0));


//         p111 111_尚硅谷_Scala_集合（六）_元组 [BV1Xh411S7bP_p111]

       /* File file = new File("/Users/qim/Downloads/scala");
        File[] files = file.listFiles();
        for (File f : files) {
            String name = f.getName();
            String p = f.getPath();
//            name = name.replace("尚硅谷大数据技术之Scala入门到精通教程（小白快速上手scala）", "");
            String[] s = name.split(" ");
            int i = name.indexOf(".");
            name = f.getParent() + File.separator + name.split(" ")[2] + name.substring(i);
            //System.out.println(p + name);
            f.renameTo(new File(name));
        }*/

       /* User user = new User();
        Consumer<User> consumer = (v) -> {
            if (v.getId() == null) {
                System.out.println(" ======= ");
            } else {
                user.setName("xxxx");
            }
        };
        user.setId(2);
        consumer.accept(user);
        System.out.println(user);*/

        /*String path2 = "/Users/qim/Downloads/42/V/";
        File f = new File(path2);
        if(f.isDirectory()){
            File[] files = f.listFiles();
            for (File file : files) {
                System.out.println(file.getName());
                String name = file.getName();
                int idx = name.indexOf("(");
                if(idx < 0){
                    continue;
                }
                name = name.substring(idx);
                name = name.replace("(", "");
                name = name.replace(")", "");
//                System.out.println(" ===== " + path2 + name);
                file.renameTo(new File(path2 + name));

            }
        }*/

        System.out.println();
        /*ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 6,
                10L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(10));

        for (int i = 0; i < 2; i++)
            executor.submit(() -> {
                try {
                    System.out.println(" " + Thread.currentThread().getName());
                    TimeUnit.SECONDS.sleep(6);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });

        try {
            System.out.println(" " + Thread.currentThread().getName());
            TimeUnit.SECONDS.sleep(6);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        executor.submit(() -> {
            try {
                System.out.println(" " + Thread.currentThread().getName());
                TimeUnit.SECONDS.sleep(6);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        executor.shutdown();


        int red = 0, blue = 0;
        int a = (int)Math.sqrt(red);
        int b = (int)Math.ceil(Math.sqrt(blue + 0.25) - 0.5);*/

       /* int a1 = 0, a2 = 0;
        //先使用，后++； => a2 = a1, a1 = a1 + 1
        a2 = a1 ++;
        System.out.println("a1 = " + a1 + ", a2 = " + a2); // a1 = 1, a2 = 0
        //先++, 使用； => a1 = a1 + 1, a2 = a1
        int b1 = 0, b2;
        b2 = ++ b1;
        System.out.println("b1 = " + b1 + ", b2 = " + b2); // b1 = 1, b2 = 1*/
    }

    @Data
    static class User {
        Integer id;
        String name;
    }

    private static void testCatch() {
        try {
            int i = 10 / 0;
        } catch (ArithmeticException e) {
            System.out.println("1 ---- ");
            throw e;
        } catch (Throwable t) {
            System.out.println("2 ---- ");
        }
    }

    private static void interruptedThread() throws InterruptedException {
        ReentrantLock lock = new ReentrantLock(true);
        Thread t1 = new Thread(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(30);
                if (lock.tryLock(1, TimeUnit.MINUTES)) {
                    log.info("get lock");
                } else {
                    log.info("unGet lock");
                }

            } catch (InterruptedException e) {
                log.error(Thread.currentThread().getName() + ": " + e.getMessage());
            } finally {
                if (lock.isLocked())
                    lock.unlock();
            }
        }, "t1");

        t1.start();

        new Thread(() -> {
            lock.lock();
            try {
                TimeUnit.MILLISECONDS.sleep(10);
                t1.interrupt();
            } catch (InterruptedException e) {
                log.error(Thread.currentThread().getName() + ": " + e.getMessage());
            } finally {
                lock.unlock();
            }
        }, "t2").start();

        TimeUnit.SECONDS.sleep(3);
    }

    private static void doWhile() {
        while (true) {
            System.out.println(" ----- ");
            if (1 == 1)
                break;
        }

        int i = 1;
        do {
            System.out.println(" +++++");
            i += 1;
        } while (i != 3);
    }

    public static void or() {
//        int i = 10;
        int i = 11;
        int y = 3;
        if (i == 10 || (y = (y + 2)) > 4) { // 第一个是true,第二个判断阻断
            System.out.println(y);
        }
        System.out.println(i + " ---- " + y);
    }

    static void renameFile() {

        String idx = "来自“English with Ronnie · EnglishLessons4U with engVid”上传的内容 - ";
        String path = "来自“English with Ronnie · EnglishLessons4U with engVid”上传的内容 - %03d - ";
        int start = 30, end = 39;
//        int start = 26, end = 31;

        Set<String> filters = new HashSet<>();
        for (int i = start; i <= end; i++) {
            String tmp = String.format(path, i);
            filters.add(tmp);
        }

        File file = new File("/Users/qim/Downloads");
//        File file = new File("/Users/qim/Downloads/EnglishLessons4U -红薯");
        File[] files = file.listFiles();
        List<File> targets = new ArrayList<>(20);
        for (File f : files) {
            if (f.isDirectory()) {
                continue;
            }
            if (f.getName().indexOf(idx) < 0) {
                continue;
            }

            targets.add(f);
        }

        for (File f : targets) {
            if (filter(filters, f.getName())) {
                fileRename(f, () -> idx);
            }
        }
    }

    private static boolean filter(Set<String> sets, String target) {
        for (String s : sets) {
            if (target.indexOf(s) >= 0) {
                return true;
            }
        }
        return false;
    }

    static class FileRemoveTargetDir {

        File root;

        public FileRemoveTargetDir(String path) {
            this.root = new File(path);
            if (!root.exists()) {
                throw new RuntimeException("no such file");
            }
        }

        public void del() {
            doDel(root);
            System.out.println("Done .. ");
        }

        private void doDel(File file) {
            if (!file.isDirectory()) {
                return;
            }
            File[] files = scan(file);
            for (File f : files) {
                deleteTarget(f);
                doDel(f);
            }
        }

        private static File[] scan(File file) {
            if (file.isDirectory()) {
                return file.listFiles();
            }
            return new File[0];
        }

        private static void deleteTarget(File file) {
            if (file.isDirectory()) {
                if ("/Users/qim/Documents/idea-code/play-own".equals(file.getName())) {
                    return;
                }
                if ("target".equals(file.getName())) {
                    FileSystemUtils.deleteRecursively(file);
                }
            }
        }
    }

    public static void main_3(String[] args) {

//        手慢无！花9680购买的付费课程【Netty源码深入剖析】现在冒死上传出来，速速收藏加观看！—Java架构-高级架构师-netty - 078 - 11-6 责任链模式在Netty里面的应用
        File file = new File("/Users/qim/Downloads");
        File[] files = file.listFiles();
        for (File f : files) {
            if (f.isDirectory()) {
                continue;
            }
            if (f.getName().indexOf("手慢无！") < 0) {
                continue;
            }
            String replace = f.getName().replace("手慢无！花9680购买的付费课程【Netty源码深入剖析】现在冒死上传出来，速速收藏加观看！—Java架构-高级架构师-netty - ", "");
            System.out.println(f.getName());
            File newFile = new File("/Users/qim/Downloads/" + replace);
            f.renameTo(newFile);
        }
    }

    private static void fileRename(File sourceFile, Supplier<String> nameFilter) {
        String replace = sourceFile.getName().replace(nameFilter.get(), "");
        replace = dup(replace);
        String path = sourceFile.getParent() + File.separator;
        File newFile = new File(path + replace);
        System.out.println(newFile.getName());
        sourceFile.renameTo(newFile);
    }

    public static String dup(String str) {
        if ((str.length() & 1) == 0) {
            int halfLen = str.length() / 2;

            if (str.substring(0, halfLen).equals(str.substring(halfLen))) {
                return str.substring(0, halfLen);
            }
        }
        return str;
    }

    public static void main_2(String[] args) throws ParseException {
        /*List<Long> storeIds = Lists.newArrayList(1L, 2L);
        logger.info("sap紧急变价同步给渠道店铺,{}", storeIds);
        System.out.println(storeIds);
        StringBuilder sb = new StringBuilder();
        sb.append("12");*/

        /*GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.setDateFormat("yyyy-MM-dd hh:mm:ss");
        gsonBuilder.registerTypeAdapter(Timestamp.class,new TimestampTypeAdapter());
        Gson gson = gsonBuilder.create();*/
        /*String xx = "[{\"channelCode\":\"210004\",\"code\":\"10003813\",\"currentPage\":0,\"defaultWarehouseType\":1,\"id\":2011110000096032,\"isJddjCanSale\":1,\"itemsPerPage\":0,\"merchantId\":2009010000000254,\"startItem\":0,\"storeId\":2009290000002302},{\"channelCode\":\"210015\",\"code\":\"10003813\",\"currentPage\":0,\"defaultWarehouseType\":1,\"id\":2011110000096062,\"isBeeleNextDayCanSale\":1,\"itemsPerPage\":0,\"merchantId\":2009010000000254,\"startItem\":0,\"storeId\":2009290000002158}]";
        Gson gson = new Gson();
        gson.fromJson(xx, new TypeToken<List<MerchantProductPO>>() {}.getType());*/

//        merchantProductPOS.get(0).set

//        System.out.println(merchantProductPOS);

//        System.out.println(Constant.v1);

        /*TestON on = new TestON();
        String ip = "222.71.209.90";//""180.162.1.74";
        String phone = "17621041535";//"17621041535";
        on.getScore(ip, phone);*/

        /*TianYuSecurityProtectionFeedbackParams p1 = new TianYuSecurityProtectionFeedbackParams();
        p1.setIp("1");

        TianYuSecurityProtectionFeedbackParams p2 = new TianYuSecurityProtectionFeedbackParams();
        p2.setIp("2");

        ConcurrentLinkedDeque<TianYuSecurityProtectionFeedbackParams> list = new ConcurrentLinkedDeque<>();
        list.add(p1);
        list.add(p2);
        List<TianYuSecurityProtectionFeedbackParams> list2 = new ArrayList<>();

        TianYuSecurityProtectionFeedbackParams p;
        while((p = list.pollFirst()) != null){
            list2.add(p);
        }
        System.out.println(list2);*/

        String xx = "数码卡、办公卡、健康卡、彩妆卡" +
                "、餐具卡、茶香卡、宠物卡、厨具卡、床品卡、服饰卡、" +
                "户外卡、护肤卡、家电卡、家居卡、家具卡、建材卡、出" +
                "行卡、美酒卡、乐器卡、生鲜卡、美发卡、母婴卡、农具" +
                "卡、配饰卡、灯具卡、食品卡、书籍卡、童装卡、文玩卡" +
                "、五金卡、洗护卡、植物卡、箱包卡、鞋履卡、药品卡、" +
                "运动卡、潮玩卡、节庆卡、厨电卡、饮料卡";
        String[] split = xx.split("、");
        System.out.println(split.length);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Random random = new Random(sdf.parse("2022-11-06 19:30:10").getTime());
        System.out.println(random);
        for (int i = 0; i < 5; i++) {
            System.out.println(split[random.nextInt(40)]);
        }

//        Arrays.stream(split).forEach(System.out::println);
    }


    public void getScore(String ip, String phoneNumber) {
        TianYuSecurityProtectionParams tianYuParams = new TianYuSecurityProtectionParams();
        tianYuParams.setIp(ip);
        tianYuParams.setPhoneNumber(phoneNumber);
        tianYuParams.setTimestamp(String.valueOf(new Date().getTime() / 1000));
        TianYuSecurityProtectionResponse response = getUserScore(tianYuParams, TianYuRequestAction.ACTIVITY_ANTI_RUSH);
        System.out.println(response);

    }

    public void setScore(String ip, String phoneNumber) {
        String resultLevel = "1";
        String interfaceName = TianYuRequestAction.ACTIVITY_ANTI_RUSH.getName();

        // 获取天御分
        TianYuSecurityProtectionFeedbackParams tianYuParams = new TianYuSecurityProtectionFeedbackParams();
        tianYuParams.setIp(ip);
        tianYuParams.setPhoneNumber(phoneNumber);
        tianYuParams.setTimestamp(String.valueOf(System.currentTimeMillis() / 1000));
        tianYuParams.setFeedbackType("1"); // * 反馈类型 0：撤销 取消历史反馈记录，下次调用 API 返回正常判别结果 1：误报 反馈天御识别为恶意的正常用户，下次调用 API 返回恶意等级 0 2：漏报 反馈天御未识别的恶意用户 ，下次调用 API 返回恶意等级 4

        tianYuParams.setResultLevel(resultLevel);
        tianYuParams.setInterfaceName(interfaceName);

        TianYuSecurityProtectionResponse tianYuResponse = feedbackUserScore(tianYuParams);
        logger.info(">>>>>>Feedback user score response: [{}]", JSON.toJSONString(tianYuResponse));
    }

    public TianYuSecurityProtectionResponse getUserScore(TianYuSecurityProtectionParams params, TianYuRequestAction
            action) {
        URI uri = new TianYuRequestBuilder().signURI(HttpMethod.GET, action, params);
        RequestEntity<Void> entity = RequestEntity.get(uri).build();

        RestTemplate restTemplate = new RestTemplate();

        ResponseEntity<TianYuSecurityProtectionResponse> response = restTemplate.exchange(entity, TianYuSecurityProtectionResponse.class);

        if (response.getStatusCodeValue() != HttpStatus.OK.value()) {//请求失败
            logger.error(">>>>>>Request tianYu security failed, request params:{}, response code:{}, response body:{}", params, response.getStatusCodeValue(), response.getBody());
        }

        TianYuSecurityProtectionResponse result = response.getBody();
        if (result == null || (result != null && result.getCode() != 0)) {
            logger.error(">>>>>>Request tian yu security failed, Response body:{}", result != null ? JSON.toJSONString(result) : "");
        }

        return result;
    }

    public TianYuSecurityProtectionResponse feedbackUserScore(TianYuSecurityProtectionFeedbackParams params) {

        RestTemplate tianYuRestTemplate = new RestTemplate();
        URI uri = new TianYuRequestBuilder().signFeedbackURI(HttpMethod.GET, params);
        RequestEntity<Void> entity = RequestEntity.get(uri).build();

        ResponseEntity<TianYuSecurityProtectionResponse> response = tianYuRestTemplate.exchange(entity, TianYuSecurityProtectionResponse.class);

        if (response.getStatusCodeValue() != HttpStatus.OK.value()) {//请求失败
            logger.error(">>>>>>Request tianYu security feedback failed, request params:{}, response code:{}, response body:{}", params, response.getStatusCodeValue(), response.getBody());
        }

        TianYuSecurityProtectionResponse result = response.getBody();
        if (result == null || (result != null && result.getCode() != 0)) {
            logger.error(">>>>>>Request tian yu security feedback failed, Response body:{}", result != null ? JSON.toJSONString(result) : "");
        }

        return result;
    }

    static class TianYuRequestBuilder {
        @Value("${akso.tencent.tian-yu.url:}")
        private String url = "csec.api.qcloud.com/v2/index.php";
        @Value("${akso.tencent.tian-yu.secret-id:}")
        private String secretId = "AKIDGLFua3wK5C7JNNvLI0VO2RYP0PZtgtUo";
        @Value("${akso.tencent.tian-yu.secret-key:}")
        private String secretKey = "FapoqGj3weDYlsllVyBJE1f6KSM8KG9o";
        @Value("${akso.tencent.tian-yu.region:}")
        private String region = "ap-shanghai";

        private String getSignContent(String method, Map<String, String> params) {
            return String.format("%s%s?%s", method, url, queryString(params, false));
        }

        private String sign(String content) {
            Mac mac = instanceHmacSHA1();
            byte[] bytes = mac.doFinal(content.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(bytes).replaceAll(System.lineSeparator(), "");
        }

        private Mac instanceHmacSHA1() {
            SecretKeySpec key = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA1");
            try {
                Mac mac = Mac.getInstance("HmacSHA1");
                mac.init(key);
                return mac;
            } catch (NoSuchAlgorithmException | InvalidKeyException e) {
                throw new RuntimeException(e);
            }
        }

        private String queryString(Map<String, String> params, boolean encode) {
            return params.entrySet().stream()
                    .map(entry -> String.format("%s=%s", entry.getKey(), encode ? urlEncode(entry.getValue()) : entry.getValue()))
                    .collect(Collectors.joining("&"));
        }

        private String urlEncode(String text) {
            try {
                return URLEncoder.encode(text, "utf-8");
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
        }

        public URI signURI(HttpMethod method, TianYuRequestAction action, TianYuSecurityProtectionParams request) {
            SortedMap<String, String> fullArgs = new TreeMap<>();
            fullArgs.put("uid", request.getPhoneNumber());
            fullArgs.put("accountType", "4");
            fullArgs.put(action.getIpKey(), request.getIp());
            fullArgs.put(action.getTimeKey(), request.getTimestamp());
            fullArgs.put("Action", action.getName());
            fullArgs.put("Nonce", String.valueOf((int) (Math.random() * 0x7fffffff)));
            fullArgs.put("Region", region);
            fullArgs.put("SecretId", secretId);
            fullArgs.put("Timestamp", String.valueOf(System.currentTimeMillis() / 1000));
            fullArgs.put("Signature", sign(getSignContent(method.name(), fullArgs)));

            String queryString = queryString(fullArgs, true);
            String url = String.format("https://%s?%s", this.url, queryString);
            return URI.create(url);
        }

        public URI signFeedbackURI(HttpMethod method, TianYuSecurityProtectionFeedbackParams request) {
            SortedMap<String, String> fullArgs = new TreeMap<>();
            fullArgs.put("uid", request.getPhoneNumber());
            fullArgs.put("accountType", "4");
            fullArgs.put("userIp", request.getIp());
            fullArgs.put("queryTime", request.getTimestamp());
            fullArgs.put("result", request.getResultLevel());
            fullArgs.put("feedbackType", request.getFeedbackType());
            fullArgs.put("interfaceName", request.getInterfaceName());
            fullArgs.put("Action", "Feedback");
            fullArgs.put("Nonce", String.valueOf((int) (Math.random() * 0x7fffffff)));
            fullArgs.put("Region", region);
            fullArgs.put("SecretId", secretId);
            fullArgs.put("Timestamp", String.valueOf(System.currentTimeMillis() / 1000));
            fullArgs.put("Signature", sign(getSignContent(method.name(), fullArgs)));

            String queryString = queryString(fullArgs, true);
            String url = String.format("https://%s?%s", this.url, queryString);
            return URI.create(url);
        }

    }


    @Data
    static class TianYuSecurityProtectionFeedbackParams {
        private String phoneNumber;
        private String ip;
        private String timestamp;
        private String resultLevel;
        private String feedbackType;
        private String interfaceName;
    }

    @Data
    static class TianYuSecurityProtectionResponse implements Serializable {

        private Integer level; //0：表示无恶意。1 - 4：恶意等级由低到高。
        private Integer code; //公共错误码：0：成功。其他值：失败。
        private String message;
        private List<Integer> riskType; //风险类型
    }

    @Data
    static class TianYuSecurityProtectionParams {
        private String phoneNumber;
        private String ip;
        private String timestamp;
    }

    enum TianYuRequestAction {
        ACTIVITY_ANTI_RUSH("ActivityAntiRush", "userIp", "postTime"),
        LOGIN_PROTECTION("LoginProtection", "loginIp", "loginTime"),
        REGISTER_PROTECTION("RegisterProtection", "registerIp", "registerTime");

        private String name;
        private String ipKey;
        private String timeKey;

        TianYuRequestAction(String name, String ipKey, String timeKey) {
            this.name = name;
            this.ipKey = ipKey;
            this.timeKey = timeKey;
        }

        public String getName() {
            return name;
        }

        public String getIpKey() {
            return ipKey;
        }

        public String getTimeKey() {
            return timeKey;
        }

    }

    public int pathSum(TreeNode root, int targetSum) {
        if (root == null) {
            return 0;
        }

        Map<Long, Integer> map = new HashMap<>();
        map.put(0L, 1);
        return helper(root, 0L, targetSum, map);
    }

    private int helper(TreeNode node, long preSum, int targetSum, Map<Long, Integer> map) {
        if (node == null) {
            return 0;
        }
        int res = 0;
        preSum += node.val;
        res += map.getOrDefault(preSum - targetSum, 0);

        map.put(preSum, map.getOrDefault(preSum, 0) + 1);

        res += helper(node.left, preSum, targetSum, map);
        res += helper(node.right, preSum, targetSum, map);

        map.put(preSum, map.getOrDefault(preSum, 0) - 1);
        //preSum -= node.val;  此行加不加没有意义了
        return res;
    }
}
